import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;

import EventPackage.Event;
import EventPackage.EventManagerInterface;
import EventPackage.EventQueue;


public class ServiceMonitor extends Thread{
	// these items are used simply for User Interaction purposes
	private JFrame thisFrame;
	private JTextArea deviceNameArea; // textually represents the state of the alarm
	
	private EventManagerInterface em = null;// Interface object to the event manager
	private boolean Registered;		// Signifies that this class is registered with an event manager.
	private String EvtMgrIP = null;			// Event Manager IP address
	private String EvtMgrName = null;
	
	private Highlighter.HighlightPainter highlighter = new DefaultHighlighter.DefaultHighlightPainter(Color.RED);
	
	private int counter = 0;
	
	private HashMap<Long, String> eventMap = new HashMap<Long, String>();
	private HashMap<Long, Integer> timeMap = new HashMap<Long, Integer>();
	
	public static void main(String args[]){
		
 		try
 		{
	 		//Use the following code for invoking the hb sender ..assuming args 2 and 3 exist. Add checks for that
	 		EventManagerInterface hbManager = new EventManagerInterface(args[0] , args[1]);
	 		
	 		ServiceMonitor monitor = new ServiceMonitor(hbManager);
	 		
	 		EventPackage.Event evt = new Event((int) 12);
	 		evt.SetSenderId(monitor.getEM().GetMyId());
	 		HeartBeat.startThread(hbManager, evt, 5000);
	 		
	 		//Use the following code for invoking the hb sender ..assuming args 2 and 3 exist. Add checks for that
 			String name = args[2];
 			String description = args[3];
	 		EventPackage.Event evt2 = new Event((int) 11, name+'%'+description);
	 		evt2.SetSenderId(monitor.getEM().GetMyId());
	 		HeartBeat.startThread(hbManager, evt2, 30000);
	 		
	 		if (monitor.IsRegistered() ){
				monitor.start(); // Here we start the monitoring and control thread
			}
	 		else{
	 			System.out.println("Unable to start the Security Monitor...");
	 		}
 		}
 		catch(Exception e)
 		{
 			System.out.println("Unable to link with the Heartbeat monitor Event Manager");
 		}

	}
	
	public ServiceMonitor(EventManagerInterface em){
		// Here we create an event manager interface object. This assumes
		// that the event manager is on the local machine
		this.em = em;
		Registered = true;
		initialize();
	}
	
	private void initialize(){
		thisFrame = new JFrame("SERVICE MONITOR");
		thisFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		thisFrame.setLayout(new BorderLayout());
		
		deviceNameArea = new JTextArea();
		deviceNameArea.setText("");
		deviceNameArea.setEditable(false);
		JScrollPane scrollPane = new JScrollPane(deviceNameArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		
		thisFrame.add(scrollPane, BorderLayout.CENTER);
		thisFrame.setSize(500, 200);
		thisFrame.setVisible(true);
	}
	
	public boolean IsRegistered()
	{
		return(Registered);
	}

	public void run(){
		Event Evt = null;				// Event object
		EventQueue eq = null;			// Message Queue
		int	Delay = 1000;				// The loop delay (1 second)
		boolean Done = false;			// Loop termination flag

		if (em != null)
		{
			while ( !Done )
			{
				// Here we get our event queue from the event manager
				try
				{
					eq = em.GetEventQueue();
				} // try
	
				catch( Exception e )
				{
					JOptionPane.showMessageDialog(null,"Error getting event queue::" + e );
				} // catch
	
				int qlen = eq.GetSize();
				
				for (int i=0; i<qlen; i++)
				{
					Evt = eq.GetEvent();
										
					switch(Evt.GetEventId())
					{
						case 11:
							handleDescriptionEvent(Evt);
							break;
							
						case 12:
							handleHeartbeatEvent(Evt);
							break;
							
						case 99:
							Done = true; 
							break;
					}// switch
				}// for
				
				deviceNameArea.setText("");
				
				for (Long senderId : eventMap.keySet()) 
				{
					String [] values = eventMap.get(senderId).split("%");
					if(values.length > 1)
					{
						deviceNameArea.append(senderId + " :: ("+ timeMap.get(senderId) +") :: " + values[0]+ " - " + values[1]);
					}
					else
					{
						deviceNameArea.append(values[0]);	
					}
					if(timeMap.get(senderId) > 10)
					{
						deviceNameArea.append(" -- NOT RESPONDING");
					}
					deviceNameArea.append("\n");
				}
				
				try
				{
					Thread.sleep( Delay );
				} // try	
				catch( Exception e )
				{
					System.out.println( "Sleep error:: " + e );
					JOptionPane.showMessageDialog(null, "SLEEP ERROR");
				} // catch
				for (Long senderId : timeMap.keySet()) 
				{
					timeMap.put(senderId, (Integer)(timeMap.get(senderId)+1));
				}
			} // while
		} 
		else {
			System.out.println("Unable to register with the event manager.\n\n" );
	
		} // if
		
	}
	
	public void handleDescriptionEvent(Event evt)
	{
		eventMap.put(new Long(evt.GetSenderId()), (String)evt.GetMessage());
		timeMap.put(new Long(evt.GetSenderId()), new Integer(0));
	}
	
	public void handleHeartbeatEvent(Event evt)
	{
		if(!eventMap.containsKey(new Long(evt.GetSenderId())))
		{
			eventMap.put(new Long(evt.GetSenderId()), evt.GetSenderId()+" :: Waiting for Name");
		}
		timeMap.put(new Long(evt.GetSenderId()), new Integer(0));
	}
	
	public EventManagerInterface getEM(){
		return em;
	}
	
}
